/*
 * @Author       : Xu Xiaokang
 * @Email        : xuxiaokang_up@qq.com
 * @Date         : 2022-01-13 21:17:02
 * @LastEditors  : Xu xiaokang
 * @LastEditTime : 2022-01-13 22:21:06
 * @Filename     :
 * @Description  :
 */

#include "Xxk_CAN.h"

/*
    PS CAN初始化函数,
*/
int psCanInti(XCanPs *psCanPtr, u16 psCan_DeviceId)
{
    XCanPs_Config *psCan_configPtr;
    psCan_configPtr = XCanPs_LookupConfig(psCan_DeviceId);
    if (psCan_configPtr == NULL)
    {
        xil_printf("psCan %d configPtr is NULL\r\n", psCan_DeviceId);
        return XST_FAILURE;
    }

    int status;
    status = XCanPs_CfgInitialize(psCanPtr, psCan_configPtr, psCan_configPtr->BaseAddr);
    if (status != XST_SUCCESS)
    {
        xil_printf("psCan %d Initialization Failed\r\n", psCan_DeviceId);
        return status;
    }

    status = XCanPs_SelfTest(psCanPtr);
    if (status != XST_SUCCESS)
    {
        xil_printf("psCan %d SelfTest Failed\r\n", psCan_DeviceId);
        return status;
    }

    xil_printf("psCan %d Initialization Succeed\r\n", psCan_DeviceId);
    return status;
}

/*
    ps CAN设置函数，设置分频系数，同步跳转宽度，时间间隔1和时间间隔2，最后确定波特率
*/
int psCanSet(XCanPs *psCanPtr, u8 Prescaler, u8 SyncJumpWidth, u8 TimeSegment2, u8 TimeSegment1)
{
    // 进入配置模式使我们可以设置波特率分频系数寄存器BRPR 以及 比特时序寄存器BTR
    XCanPs_EnterMode(psCanPtr, XCANPS_MODE_CONFIG); // 初始化结束就已经是配置模式了

    while (XCanPs_GetMode(psCanPtr) != XCANPS_MODE_CONFIG)
        ; // 等待进入配置模式

    /*
   * Setup Baud Rate Prescaler Register (BRPR) and
   * Bit Timing Register (BTR).
   */
    int status;
    status = XCanPs_SetBaudRatePrescaler(psCanPtr, Prescaler);
    if (status != XST_SUCCESS)
    {
        xil_printf("psCan Set Baud Rate Prescaler Failed\r\n");
        return status;
    }

    status = XCanPs_SetBitTiming(psCanPtr, SyncJumpWidth, TimeSegment2, TimeSegment1);
    if (status != XST_SUCCESS)
    {
        xil_printf("psCan Set Bit Timing Failed\r\n");
        return status;
    }

    xil_printf("psCan Set Succeed\r\n");
    return status;
}

/*
    PS CAN设置发送帧头，可选标准帧和扩展帧两种
*/
void psCan_SetTxFrameHeader(u32 *FramePtr, u32 stardardOrExtended, u32 message_id, u32 frame_data_length)
{
    if (STANDARD_FRAME == 0)
    {
        FramePtr[0] = (u32)XCanPs_CreateIdValue((u32)message_id, 0, 0, 0, 0); // 标准帧
        xil_printf("psCan Set STANDARD_FRAME\r\n");
    }
    else if (STANDARD_FRAME == 1)
    {
        FramePtr[0] = (u32)XCanPs_CreateIdValue((u32)0, 0, 1, message_id, 0); // 扩展帧
        xil_printf("psCan Set EXTENDED_FRAME\r\n");
    }
    else
    {
        xil_printf("psCan Set Frame type error!\r\n");
    }

    FramePtr[1] = (u32)XCanPs_CreateDlcValue((u32)frame_data_length);
}

//int psCan_LoopBackTest(XCanPs *psCanPtr, u32 *)
//{
//    // 进入回环模式，进行发收测试
//    XCanPs_EnterMode(psCanPtr, XCANPS_MODE_LOOPBACK);
//
//    while (XCanPs_GetMode(psCanPtr) != XCANPS_MODE_LOOPBACK)
//        ; // 等待进入回环模式
//
//    /*
//   * Send a frame, receive the frame via the loop back and verify its contents.
//   */
//    int status;
//    status = psCan_SendFrame(psCanPtr, );
//    if (status != XST_SUCCESS)
//    {
//        xil_printf("psCan Send Frame Failed\r\n");
//        return status;
//    }
//
//    status = psCan_RecvFrame(psCanPtr);
//    if (status != XST_SUCCESS)
//    {
//        xil_printf("psCan Recv Frame Failed\r\n");
//        return status;
//    }
//
//    xil_printf("psCan Loop Back Test Succeed\r\n");
//    return status;
//}

/*
    PS CAN中断的联系中断函数和使能中断，在此之前需要先实例化scuGic并使能中断
*/
void psCan_IntrSetAndEnable(XScuGic *scuGicPtr, u32 psCan_IntrId, XCanPs *psCanPtr, u32 mask)
{
    XScuGic_Connect(scuGicPtr, psCan_IntrId,
                    (Xil_InterruptHandler)XCanPs_IntrHandler,
                    (void *)psCanPtr);
    XScuGic_Enable(scuGicPtr, psCan_IntrId);
    XCanPs_IntrEnable(psCanPtr, mask); // XCANPS_IXR_ALL
}

/*
    PS CAN的设置中断处理函数
*/
void psCan_SetHandler(XCanPs *psCanPtr)
{
    XCanPs_SetHandler(psCanPtr, XCANPS_HANDLER_SEND, (void *)psCan_SendHandler, (void *)psCanPtr);
    XCanPs_SetHandler(psCanPtr, XCANPS_HANDLER_RECV, (void *)psCan_RecvHandler, (void *)psCanPtr);
    XCanPs_SetHandler(psCanPtr, XCANPS_HANDLER_ERROR, (void *)psCan_ErrorHandler, (void *)psCanPtr);
    XCanPs_SetHandler(psCanPtr, XCANPS_HANDLER_EVENT, (void *)psCan_EventHandler, (void *)psCanPtr);
}

/*
    中断处理函数的虚函数，同名用户函数将覆盖此函数
*/
__weak void psCan_SendHandler(void *CallBackRef)
{
}

__weak void psCan_RecvHandler(void *CallBackRef)
{
}

__weak void psCan_ErrorHandler(void *CallBackRef)
{
}

__weak void psCan_EventHandler(void *CallBackRef)
{
}
